#include "wfnet_mt.h"

#include <bool.h>
#include <boolproxy.h>
#include <bstring.h>
#include <bstringproxy.h>
#include <dynamictypemanager.h>
#include <expressionengine.h>
#include <expressionvalidator.h>
#include <iarc.h>
#include <iplace.h>
#include <multisetproxy.h>
#include <netrunnable.h>
#include <netrunner.h>
#include <number.h>
#include <numberproxy.h>
#include <timedmultisetproxy.h>
#include <typefactory.h>
#include <wfnet.h>

#include <QtTest/QTest>

using namespace core;
using namespace wfnet;
using namespace moduletest;

void WfNet_mt::initTestCase()
{
    Bool boolean;
    BasicString string;
    Number number;

    m_net = new WfNet(this);

    DynamicTypeManager::getInstance()->registerColorSet(
        "Booleans", boolean, m_net);
    DynamicTypeManager::getInstance()->registerColorSet(
        "Strings", string, m_net);
    DynamicTypeManager::getInstance()->registerColorSet(
        "Numbers", number, m_net);
    DynamicTypeManager::getInstance()->registerColorSet(
        "NumbersTimed", number, m_net, true);

    DynamicTypeManager::getInstance()->registerVariable(
        "b", "Booleans", m_net);

    DynamicTypeManager::getInstance()->registerVariable(
        "s", "Strings", m_net);
    DynamicTypeManager::getInstance()->registerVariable(
        "t", "Strings", m_net);

    DynamicTypeManager::getInstance()->registerVariable(
        "n", "Numbers", m_net);
    DynamicTypeManager::getInstance()->registerVariable(
        "k", "Numbers", m_net);

    DynamicTypeManager::getInstance()->registerVariable(
        "nTimed", "NumbersTimed", m_net);
    DynamicTypeManager::getInstance()->registerVariable(
        "kTimed", "NumbersTimed", m_net);

    ExpressionValidator::getInstance()->registerKeywordMasks(
        TypeFactory::getInstance()->registeredKeywordMasks());

    ExpressionEngine::getInstance()->registerTypeProxy(Bool::NAME,
        BoolProxy::NAME);
    ExpressionEngine::getInstance()->registerTypeProxy(BasicString::NAME,
        BasicStringProxy::NAME);
    ExpressionEngine::getInstance()->registerTypeProxy(Number::NAME,
        NumberProxy::NAME);
    ExpressionEngine::getInstance()->registerTypeProxy(Multiset::NAME,
        MultisetProxy::NAME);
    ExpressionEngine::getInstance()->registerTypeProxy(TimedMultiset::NAME,
        TimedMultisetProxy::NAME);
}

void WfNet_mt::run()
{
    ColorSet numbers = *(dynamic_cast<const ColorSet*>(
        TypeFactory::getInstance()->getTypeInstance("Numbers")));

    Multiset ms("Numbers", "{1*1}");

    IPlace* p1_1 = m_net->addPlace(&numbers, "p1_1");
    p1_1->putTokens(&ms);
    IPlace* p2_1 = m_net->addPlace(&numbers, "p2_1");

    ITransition* t1_1 = m_net->addTransition("t1_1");

    IExpression* e11_11 = m_net->addExpression("n", "Numbers");
    IExpression* e21_11 = m_net->addExpression("n", "Numbers");

    IArc* a11_11 = m_net->connect(p1_1, t1_1);
    a11_11->setExpression(e11_11);
    IArc* a21_11 = m_net->connect(t1_1, p2_1);
    a21_11->setExpression(e21_11);

    m_net->run(1);
    NetRunnable* runnable = NetRunner::getInstance()->getRunnable(m_net);
    runnable->thread()->wait();

    QVERIFY(p1_1->getTokens()->toValue() == "{}" && p2_1->getTokens()->toValue() == "{1*1}");
}

void WfNet_mt::cleanupTestCase()
{
    DynamicTypeManager::getInstance()->unregisterColorSet("Booleans",
        m_net);
    DynamicTypeManager::getInstance()->unregisterColorSet("Strings",
        m_net);
    DynamicTypeManager::getInstance()->unregisterColorSet("Numbers",
        m_net);
    DynamicTypeManager::getInstance()->unregisterVariable("b", m_net);
    DynamicTypeManager::getInstance()->unregisterVariable("s", m_net);
    DynamicTypeManager::getInstance()->unregisterVariable("t", m_net);
    DynamicTypeManager::getInstance()->unregisterVariable("n", m_net);
    DynamicTypeManager::getInstance()->unregisterVariable("k", m_net);

    ExpressionValidator::getInstance()->clearKeywordMasks();

    ExpressionEngine::getInstance()->unregisterTypeProxy(Bool::NAME);
    ExpressionEngine::getInstance()->unregisterTypeProxy(BasicString::NAME);
    ExpressionEngine::getInstance()->unregisterTypeProxy(Number::NAME);
    ExpressionEngine::getInstance()->unregisterTypeProxy(TimedMultiset::NAME);
}
